package com.isky.visual.design.sqlparsefactory;

import com.isky.visual.db.entity.*;
import com.isky.visual.exception.GlobalException;
import com.isky.visual.result.CodeMsg;
import org.apache.commons.lang3.StringUtils;

import java.util.*;

/**
 * @version v1.0
 * @ProjectName visual_parent
 * @ClassName AbstractSqlParse
 * @Description TODO 解析通用sql 的方法
 * @Author wudl
 * @Date DATE{TIME}
 */

public abstract class AbstractSqlParse implements ISqlParse {

    private String selectColumn = "";
    private String mainFrom = "";
    private String joinSql = "";
    private String whereSql = "";
    private String dm = "";
    private String groupBySql = "";


    /**
     * 别名
     */
    private List<String> aliasList = null;
    private int aliasIndex = 0;
    //记录全外连接次数，目前2个以上不支持解析
    protected int outerCount = 0;
    protected int joinCount = 0;

    private Map<String, String> aliasCache;


    @Override
    public String parse(GenericSqlModel genericSqlModel) {
        init();
        if (genericSqlModel == null) {
            return "";
        }
        parseMain(genericSqlModel);

        parseSelect(genericSqlModel.getIndexObj());

        parseWhere(genericSqlModel.getSizerObj());


        return buildSql();
    }

    private void init() {
        String str = "a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,b,q";
        aliasList = new ArrayList(Arrays.asList(str.split(",")));
        aliasCache = new HashMap<>();
    }

    /**
     * 获取表对应的别名
     *
     * @param tableName
     * @return
     */
    protected String getAlias(String tableName) {
        String alias = this.aliasCache.get(tableName);
        if (StringUtils.isEmpty(alias)) {
            alias = this.aliasList.remove(0);
            if (StringUtils.isEmpty(alias)) {
                alias = getAlias(tableName);
            }

            this.aliasCache.put(tableName, alias);
        }

        return alias;
    }

    /**
     * 解析主节点
     */
    private void parseMain(GenericSqlModel genericSqlModel)  {
        //主表查询只有一个，所以只要处理第一个节点
        if (genericSqlModel == null) {
            throw new GlobalException(CodeMsg.DATA_PARSE_ERROR);
        }
        // 获取数据库id
        Long dbid = genericSqlModel.getDbid();

        List<VclList> vclList = genericSqlModel.getVclList();

        if (vclList == null || vclList.isEmpty()) {
            throw new GlobalException(CodeMsg.DATA_PARSE_ERROR);
        }
        String dbname = genericSqlModel.getDbName();
        VclList vclList1 = vclList.get(0);
        // 获取跟表
        doParseMain(vclList1,dbname);

        List<Children> children = vclList1.getChildren();
        if (children != null && children.size() > 0) {
            parseChildren(children, vclList1.getTablename(),dbname);
        }
    }

    /**
     * 解析子节点
     */
    private void parseChildren(List<Children> children, String parentTableName,String dbname) {
        if (children == null) {
            return;
        }
        for (Children child : children) {

            doParseChildren(child, parentTableName,dbname);
            joinCount++;

            //处理子节点
            List<Children> childrenNode = child.getChildren();
            if (childrenNode != null && childrenNode.size() > 0) {
                parseChildren(childrenNode, child.getTablename(),dbname);
            }
        }
    }

    private void parseSelect(IndexObj indexObj) {
        doParseSelect(indexObj);
    }

    private void parseWhere(SizerObj sizerObj) {
        doParseWhere(sizerObj);
    }
//    private  void parseDm()
//    {
//        doParseDm
//    }

    /**
     * 累计拼接列
     * @param column
     */
    protected void appendSelectColumn(String column) {
        if (StringUtils.isEmpty(column)) {
            return;
        }

        this.selectColumn +=column.trim() + ",";
    }

    protected void appendMainTable(String tableName) {
        if (StringUtils.isEmpty(tableName)) {
            return;
        }
        String tablenames = tableName.trim();
        this.mainFrom = tablenames;
    }

    /**
     * 累计拼接 关联 字段
     * @param joinSql
     */
    protected void appendJoinSql(String joinSql) {
        if (StringUtils.isEmpty(joinSql)) {
            return;
        }

        this.joinSql += joinSql.trim()+" ";
    }

    protected void appendWhereSql(String where) {
        if (StringUtils.isEmpty(where)) {
            return;
        }

        where = where.replace("WHERE", "")
                .replace("where", "")
                .trim();

        if (StringUtils.isEmpty(this.whereSql)) {
            where = String.format("where %s", where);
        }

        this.whereSql += where + " ";
    }

    protected void appendGroupSql(String groupBySql) {
        if (StringUtils.isEmpty(groupBySql)) {
            return;
        }
        this.groupBySql += groupBySql.trim() + ",";
    }


    protected String buildSql() {
        if(outerCount >=1 && joinCount >1){
            return "";
        }

        String candidateSql = "";
        String column = this.selectColumn;

        if (StringUtils.isEmpty(column)) {
            column = "*";
        }

        column = column.trim();
        if (column.endsWith(",")) {
            column = column.substring(0, column.length() - 1);
        }
        groupBySql = groupBySql.trim();
        if (groupBySql.endsWith(",")) {
            groupBySql = groupBySql.substring(0, groupBySql.length() - 1);
        }
        if(!StringUtils.isBlank(groupBySql)){
            groupBySql = " group by " + groupBySql;
        }
        if(!StringUtils.isBlank(whereSql)){
            //去除最后一个and 或者 or
            whereSql = whereSql.substring(0,whereSql.length()-4) ;
        }

        if(outerCount >=1){
            String joinSql = this.joinSql.replace("outer","left");
            String candidateSql1 = String.format(" select %s from %s %s %s %s ",
                    column,
                    this.mainFrom,
                    joinSql,
                    this.whereSql,
                    this.groupBySql
            );

            joinSql = this.joinSql.replace("outer","right");
            String candidateSql2 = String.format(" select %s from %s %s %s %s ",
                    column,
                    this.mainFrom,
                    joinSql,
                    this.whereSql,
                    this.groupBySql
            );

            candidateSql = String.format("%s union %s",
                    candidateSql1,candidateSql2
            );
        }else {
            candidateSql = String.format(" select %s from %s %s %s %s ",
                    column,
                    this.mainFrom,
                    this.joinSql,
                    this.whereSql,
                    this.groupBySql
            );
        }

        return candidateSql;
    }


    public void doParseMain(VclList vclList,String dbname) {

    }

    protected void doParseChildren(Children child, String parentTableName,String dbname) {
    }

    protected void doParseSelect(IndexObj indexObj) {
    }

    protected void doParseWhere(SizerObj sizerObj) {
    }

    protected void doParseDm(SizerObj sizerObj) {
    }
}
